import oss2
import os
from dotenv import load_dotenv
from io import BytesIO
import base64
import uuid

# 加载 .env 文件中的环境变量
load_dotenv()

# 从环境变量获取 OSS 配置信息
access_key_id = os.getenv('OSS_ACCESS_KEY_ID')
access_key_secret = os.getenv('OSS_ACCESS_KEY_SECRET')
endpoint = os.getenv('OSS_ENDPOINT')
bucket_name = os.getenv('OSS_BUCKET_NAME')

# 检查配置是否齐全
if not all([access_key_id, access_key_secret, endpoint, bucket_name]):
    raise RuntimeError("OSS 配置环境变量不全")

# 初始化 OSS 认证和 Bucket 实例
auth = oss2.Auth(access_key_id, access_key_secret)
bucket = oss2.Bucket(auth, endpoint, bucket_name)


def upload_file(object_name: str, file_bytes: bytes):
    """
    上传文件到 OSS。
    :param object_name: OSS 中的对象名（文件名）
    :param file_bytes: 文件内容（二进制）
    :return: 上传结果
    """
    result = bucket.put_object(object_name, file_bytes)
    return result


def download_file(object_name: str):
    """
    从 OSS 下载文件。
    :param object_name: OSS 中的对象名
    :return: 文件内容的 BytesIO 流
    """
    obj = bucket.get_object(object_name)
    return BytesIO(obj.read())


def list_files():
    """
    列出 Bucket 中所有对象名。
    :return: 对象名列表
    """
    return [obj.key for obj in oss2.ObjectIterator(bucket)]


def delete_file(object_name: str):
    """
    删除 OSS 中的单个对象。
    :param object_name: OSS 中的对象名
    :return: 删除结果
    """
    result = bucket.delete_object(object_name)
    return result


def batch_delete_files(object_names: list):
    """
    批量删除 OSS 中的对象。
    :param object_names: 对象名列表
    :return: 实际删除的对象名列表
    """
    result = bucket.batch_delete_objects(object_names)
    return result.deleted_keys


def get_object_metadata(object_name: str):
    """
    获取 OSS 对象的元信息（如大小、最后修改时间等）。
    :param object_name: OSS 中的对象名
    :return: 元信息字典
    """
    meta = bucket.head_object(object_name)
    return {
        'size': meta.content_length,
        'last_modified': meta.last_modified,
        'etag': meta.etag,
        'content_type': meta.content_type
    }


def check_object_exists(object_name: str):
    """
    检查 OSS 对象是否存在。
    :param object_name: OSS 中的对象名
    :return: 存在返回 True，否则 False
    """
    try:
        bucket.head_object(object_name)
        return True
    except oss2.exceptions.NoSuchKey:
        return False


def set_object_acl(object_name: str, acl: str):
    """
    设置 OSS 对象的访问权限（ACL）。
    :param object_name: OSS 中的对象名
    :param acl: 权限类型（如 oss2.OBJECT_ACL_PRIVATE 等）
    :return: True
    """
    bucket.put_object_acl(object_name, acl)
    return True


def get_object_acl(object_name: str):
    """
    获取 OSS 对象的访问权限（ACL）。
    :param object_name: OSS 中的对象名
    :return: 权限类型字符串
    """
    result = bucket.get_object_acl(object_name)
    return result.acl


def generate_signed_url(object_name: str, expires: int = 3600):
    """
    生成 OSS 对象的签名 URL，可临时访问。
    :param object_name: OSS 中的对象名
    :param expires: 有效期（秒）
    :return: 签名 URL
    """
    url = bucket.sign_url('GET', object_name, expires)
    return url


def copy_object(source_object_name: str, target_object_name: str):
    """
    复制 OSS 中的对象到新对象名。
    :param source_object_name: 源对象名
    :param target_object_name: 目标对象名
    :return: 复制结果
    """
    result = bucket.copy_object(bucket.bucket_name, source_object_name, target_object_name)
    return result


async def upload_base64_image(image_base64: str) -> str:
    """
    接收base64图片字符串，上传到OSS，返回可访问的URL。
    用于对话消息中的图片上传。
    """
    # 解析base64
    if "," in image_base64:
        image_base64 = image_base64.split(",", 1)[1]
    image_bytes = base64.b64decode(image_base64)
    # 生成唯一文件名 - 改为chat_images文件夹
    object_name = f"chat_images/{uuid.uuid4().hex}.png"
    upload_file(object_name, image_bytes)
    # 拼接OSS公开URL
    oss_url = f"https://{bucket_name}.{endpoint.replace('https://', '').replace('http://', '')}/{object_name}"
    return oss_url


async def upload_detection_image(image_base64: str) -> str:
    """
    接收base64图片字符串，上传到OSS，返回可访问的URL。
    用于检测结果的图片上传。
    """
    # 解析base64
    if "," in image_base64:
        image_base64 = image_base64.split(",", 1)[1]
    image_bytes = base64.b64decode(image_base64)
    # 生成唯一文件名 - 检测结果使用detection_images文件夹
    object_name = f"detection_images/{uuid.uuid4().hex}.png"
    upload_file(object_name, image_bytes)
    # 拼接OSS公开URL
    oss_url = f"https://{bucket_name}.{endpoint.replace('https://', '').replace('http://', '')}/{object_name}"
    return oss_url

